package corp.edu.amadeus.core.dao.impl.callback;

import java.lang.reflect.Method;
import java.sql.SQLException;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.Order;
import org.springframework.orm.hibernate3.HibernateCallback;
import corp.edu.amadeus.core.business.object.ifc.IPersistable;
import corp.edu.amadeus.commons.Constants;

public class GenericFindCallbackWithOrder implements HibernateCallback {

    private final Class<?> po;

    private final Method[] methods;

    private final Object[] reqResults;

    private final String orderProperty;

    private final String orderType;

    private final int maxResults;

    public GenericFindCallbackWithOrder(Class<?> po, Method[] methods,
            Object[] reqResults, String orderProperty , String orderType, int maxResults) {
        super();
        if (!IPersistable.class.isAssignableFrom(po)) {
            System.out.println(po.getClass().getName() + " is"
                    + " not persistable (i.e. doesn't extend IPersistable");
           /* throw new NotPersistableException(po.getClass().getName() + " is"
                    + " not persistable (i.e. doesn't extend IPersistable");*/
        }
        this.po = po;
        this.methods = methods;
        this.reqResults = reqResults;
        this.orderProperty = orderProperty;
        this.orderType = orderType;
        this.maxResults = maxResults;
    }

    public GenericFindCallbackWithOrder(Class<?> po, Method[] methods,
            Object[] reqResults, String orderProperty , String orderType) {
        super();
        if (!IPersistable.class.isAssignableFrom(po)) {
            System.out.println(po.getClass().getName() + " is"
                    + " not persistable (i.e. doesn't extend IPersistable");
           /* throw new NotPersistableException(po.getClass().getName() + " is"
                    + " not persistable (i.e. doesn't extend IPersistable");*/
        }
        this.po = po;
        this.methods = methods;
        this.reqResults = reqResults;
        this.orderProperty = orderProperty;
        this.orderType = orderType;
        this.maxResults = 0;
    }

    public Object doInHibernate(Session session) throws HibernateException,
            SQLException {
        Criteria crit = session.createCriteria(this.po);
        for (int i = 0; i < methods.length; i++) {
            String metName = this.translate(methods[i]);
            crit.add(Expression.eq(metName, reqResults[i]));
        }
        if(Constants.ASC_ORDER.equals(this.orderType)) {
            crit.addOrder(Order.asc(this.orderProperty));
        }else {
            crit.addOrder(Order.desc(this.orderProperty));
        }

        if(this.maxResults>0) {
            crit.setMaxResults(this.maxResults);
        }

        return crit.list();
    }

    private String translate(Method met) {
        String name = met.getName();
        if (name.startsWith("get")) {
            name = name.substring("get".length(), name.length());
            name = Character.toLowerCase(name.charAt(0)) + name.substring(1);
        }
        return name;
    }

}